package com.kevin.io.netty;

import com.kevin.io.netty.entity.User;
import com.kevin.io.netty.handler.DefaultChannelInboundHandlerAdapter;
import com.kevin.io.netty.util.ChannelHandlerUtils;
import com.kevin.io.netty.util.NettyStudyUtils;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.nio.charset.StandardCharsets;

/**
 * @author Kevin Liu
 */
public class NettyClient {

    public static void main(String[] args) throws InterruptedException {
        fourthTest();
    }

    /**
     * 普通Netty测试
     * @throws InterruptedException
     */
    public static void fourthTest()throws InterruptedException{
        start(ChannelHandlerUtils.thirdTest(new DefaultChannelInboundHandlerAdapter(){

            private int count = 0;
            @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                User user = new User();
                user.setId(1L);
                user.setName("kevin");
                for (int i = 0; i < 100; i++) {
                    ctx.write(user);
                }
                ctx.flush();
            }

            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                System.out.println("body:" + msg);
                System.out.println("count:" + ++count);
                ctx.close();
            }
        }));
    }

    /**
     * 普通Netty测试
     * @throws InterruptedException
     */
    public static void firstTest()throws InterruptedException{
        start(ChannelHandlerUtils.firstTest(new DefaultChannelInboundHandlerAdapter(){
            @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                ByteBuf message;
                final byte[] bytes = NettyStudyUtils.getMessage("hello netty").getBytes(StandardCharsets.UTF_8);
                message = Unpooled.buffer(bytes.length);
                message.writeBytes(bytes);
                ctx.writeAndFlush(message);
            }

            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                ByteBuf buf = (ByteBuf) msg;
                final byte[] bytes = new byte[buf.readableBytes()];
                buf.readBytes(bytes);
                String body = new String(bytes, StandardCharsets.UTF_8);
                System.out.println("body:" + body);
                ctx.close();
            }
        }));
    }
    /**
     * 普通Netty测试
     * @throws InterruptedException
     */
    public static void secondTest()throws InterruptedException{
        start(ChannelHandlerUtils.firstTest(new DefaultChannelInboundHandlerAdapter(){

            private int count = 0;
            @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                ByteBuf message;
                final byte[] bytes = NettyStudyUtils.getMessage("hello netty").getBytes();
                for (int i = 0; i < 100; i++) {
                    message = Unpooled.buffer(bytes.length);
                    message.writeBytes(bytes);
                    ctx.writeAndFlush(message);
                }

            }

            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                ByteBuf buf = (ByteBuf) msg;
                final byte[] bytes = new byte[buf.readableBytes()];
                buf.readBytes(bytes);
                String body = new String(bytes, StandardCharsets.UTF_8);
                System.out.println("body:" + body);
                System.out.println("count:" + ++count);
                ctx.close();
            }
        }));
    }

    /**
     * 普通Netty测试
     * @throws InterruptedException
     */
    public static void thirdTest()throws InterruptedException{
        start(ChannelHandlerUtils.secondTest(new DefaultChannelInboundHandlerAdapter(){

            private int count = 0;
            @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                ByteBuf message;
                final byte[] bytes = NettyStudyUtils.getMessage("hello netty").getBytes();
                for (int i = 0; i < 100; i++) {
                    message = Unpooled.buffer(bytes.length);
                    message.writeBytes(bytes);
                    ctx.writeAndFlush(message);
                }

            }

            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                String body = (String) msg;
                System.out.println("body:" + body);
                System.out.println("count:" + ++count);
                ctx.close();
            }
        }));
    }




    public static void start(ChannelHandler channelHandler) throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup();
        try{
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY,true)
                    .handler(channelHandler);
            final ChannelFuture sync = b.connect("127.0.0.1", 8080).sync();
            sync.channel().closeFuture().sync();
        }finally {
            group.shutdownGracefully();
        }
    }
}
